Import and format data

Import IPUMS

Use of data from IPUMS USA is subject to conditions including that users should
cite the data appropriately. Use command `ipums_conditions()` for more details.

|=                                                                                                         |   1%    6 MB
|===                                                                                                       |   3%   13 MB
|=====                                                                                                     |   5%   19 MB
|=======                                                                                                   |   7%   26 MB
|=========                                                                                                 |   9%   32 MB
|===========                                                                                               |  10%   39 MB
|=============                                                                                             |  12%   45 MB
|===============                                                                                           |  14%   52 MB
|=================                                                                                         |  16%   58 MB
|===================                                                                                       |  18%   65 MB
|=====================                                                                                     |  19%   71 MB
|=======================                                                                                   |  21%   78 MB
|=========================                                                                                 |  23%   84 MB
|===========================                                                                               |  25%   91 MB
|============================                                                                              |  27%   97 MB
|==============================                                                                            |  28%  104 MB
|================================                                                                          |  30%  110 MB
|==================================                                                                        |  32%  117 MB
|====================================                                                                      |  34%  123 MB
|======================================                                                                    |  36%  130 MB
|========================================                                                                  |  37%  136 MB
|==========================================                                                                |  39%  143 MB
|============================================                                                              |  41%  149 MB
|==============================================                                                            |  43%  156 MB
|================================================                                                          |  45%  162 MB
|==================================================                                                        |  46%  169 MB
|====================================================                                                      |  48%  175 MB
|======================================================                                                    |  50%  182 MB
|=======================================================                                                   |  52%  188 MB
|=========================================================                                                 |  54%  195 MB
|===========================================================                                               |  55%  201 MB
|=============================================================                                             |  57%  208 MB
|===============================================================                                           |  59%  214 MB
|=================================================================                                         |  61%  221 MB
|===================================================================                                       |  63%  227 MB
|=====================================================================                                     |  64%  234 MB
|=======================================================================                                   |  66%  240 MB
|=========================================================================                                 |  68%  247 MB
|===========================================================================                               |  70%  253 MB
|=============================================================================                             |  72%  260 MB
|===============================================================================                           |  73%  266 MB
|=================================================================================                         |  75%  273 MB
|==================================================================================                        |  77%  279 MB
|====================================================================================                      |  79%  286 MB
|======================================================================================                    |  81%  292 MB
|========================================================================================                  |  82%  299 MB
|==========================================================================================                |  84%  305 MB
|============================================================================================              |  86%  312 MB
|==============================================================================================            |  88%  318 MB
|================================================================================================          |  90%  325 MB
|==================================================================================================        |  91%  331 MB
|====================================================================================================      |  93%  338 MB
|======================================================================================================    |  95%  344 MB
|========================================================================================================  |  97%  351 MB
|==========================================================================================================|  99%  357 MB
|===========================================================================================================| 100%  360 MB

PUMA shapefiles

OGR data source with driver: ESRI Shapefile 
Source: "/Users/chriszs/Desktop/work/covid-immigrant-foodworkers/data/ipums_puma_2010/ipums_puma_2010.shp", layer: "ipums_puma_2010"
with 2378 features
It has 7 fields
Integer64 fields read as strings:  GISMATCH 

County shapefiles

OGR data source with driver: ESRI Shapefile 
Source: "/Users/chriszs/Desktop/work/covid-immigrant-foodworkers/data/tl_2019_us_county/tl_2019_us_county.shp", layer: "tl_2019_us_county"
with 3233 features
It has 17 fields
Integer64 fields read as strings:  ALAND AWATER 

COVID county cases and deaths

covid <- read_csv("data/us-counties.csv",
                  col_types = cols(.default = "?", date = "D")) %>%
  rename(county_code = fips) %>%
  # Filter to the latest data for each county
  group_by(county_code) %>%
  slice(which.max(date))

covid

County populations

Read-in Census API key

census_key <- (readLines(key_file)[1])

Create list of all US states to iterate through in the API calls

us <- unique(fips_codes$state)[1:51]

us
 [1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "DC" "FL" "GA" "HI" "ID" "IL" "IN" "IA" "KS" "KY" "LA" "ME" "MD" "MA" "MI"
[24] "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ" "NM" "NY" "NC" "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[47] "VA" "WA" "WV" "WI" "WY"

Download population data from the 2014-2018 ACS

PUMA-to-county crosswalk

county_to_puma_crosswalk <- read_csv("data/geocorr2018.csv", skip = 1) %>%
  mutate(puma_code = paste0(`State code`, `PUMA (2012)`)) %>%
  select(
    puma_code,
    county_code = `County code (2014)`,
    state = `State abbreviation`,
    county = `2014 county name`,
    puma = `PUMA12 name`,
    allocation_factor = `puma12 to county14 allocation factor`
  )

county_to_puma_crosswalk

Join the COVID, population and crosswalk data frames

crosswalk <- list(covid, population, county_to_puma_crosswalk) %>%
  reduce(full_join, by = "county_code") %>%
  mutate(
    puma = paste(puma, state.x, sep = ", "),
    cases_per_100k = round(cases / population * 100000, digits = 0),
    deaths_per_100k = round(deaths / population * 100000, digits = 0)
  ) %>%
  select(
    1,
    state = state.x,
    county_code,
    county = county.y,
    puma_code,
    puma,
    population,
    cases,
    deaths,
    cases_per_100k,
    deaths_per_100k,
    allocation_factor
  )

crosswalk

Filter to the food production industries we’re interested in

food_production_industries <-
  list("0170", # Crop production
       "0180", # Animal production and aquaculture
       "0290", # Support activities for agriculture and forestry
       "1070", # Animal food, grain and oilseed milling
       "1080", # Sugar and confectionery products
       "1090", # Fruit and vegetable preserving and specialty food manufacturing
       "1170", # Dairy product manufacturing
       "1180", # Animal slaughtering and processing
       "1270", # Bakeries and tortilla manufacturing, except retail bakeries
       "1280", # Seafood and other miscellaneous foods; n.e.c.
       "1290") # Not specified food industries

ipums_food_production <- ipums %>%
  filter(industry_code %in% food_production_industries)

Calculate employment by industry-occupation grouping

ipums_food_production_employment_by_ind_occ <-
  ipums_food_production %>%
  group_by(industry, occupation) %>%
  summarize(num_employees = sum(PERWT)) %>%
  pivot_wider(
    id_cols = c(industry, occupation),
    values_from = num_employees,
    names_prefix = "num_employees"
  ) %>%
  replace(is.na(.), 0) %>%
  # Exclude from our analysis ind-occ groupings
  # with fewer than 2,500 employees nationally
  filter(num_employees >= 2500)

Export the data

write_csv(
  ipums_food_production_employment_by_ind_occ,
  "data/exported/ipums_food_production_employment_by_ind_occ.csv"
)

Filter the industry-occupation pairs

Import data frame of food production industry-occupation pairs

ipums_food_production_employment_by_ind_occ <-
  read_csv("data/ipums_food_production_total_employment_by_ind_occ.csv")

Join the industry-occupation pairs to the ipums data and filter to just the industry-occupation pairs we want

ipums_food_production_selected_occupations <-
  ipums_food_production %>%
  inner_join(ipums_food_production_employment_by_ind_occ,
             by = c("industry", "occupation")) %>%
  filter(exclude == FALSE) %>%
  select(-num_employees, -exclude)

ipums_food_production_selected_occupations

And join with the pumas data frame to get the PUMA names

ipums_food_production_selected_occupations <-
  ipums_food_production_selected_occupations %>%
  left_join(pumas, by = "puma_code") %>%
  mutate(puma = paste(puma, state, sep = ", ")) %>%
  select(1:3,
         13,
         4:12)

ipums_food_production_selected_occupations
citizenship_lookup = tibble(
  citizenship_code = factor(c(
    0, 1, 2, 3, 4, 5
  )),
  citizenship = c(
    "native_citizen", # n/a
    "native_citizen", # born_abroad_citizen
    "naturalized_citizen", # naturalized_citizen
    "non_citizen", # non_citizen
    "non_citizen_with_papers", # non_citizen_with_papers
    "foreign_born_status_unknown"
  )
)

ethnicity_lookup = tibble(
  ethnicity_code = factor(c(
    0, 1, 2, 3, 4, 9
  )),
  ethnicity = c(
    "non_hispanic",
    "hispanic", # mexican
    "hispanic", # puerto_rican
    "hispanic", # cuban
    "hispanic", # other
    "not_reported"
  )
)

ipums_food_production_selected_occupations_mapped <-
  ipums_food_production_selected_occupations %>%
  select(-ethnicity,-citizenship) %>%
  left_join(ethnicity_lookup, by="ethnicity_code") %>%
  left_join(citizenship_lookup, by="citizenship_code")
pct <- function (part,whole) {
  round(part / whole * 100, digits = 0)
}
calc_percents <- function (rows) {
  rows %>%
  mutate(
    total_native_citizen = (
      total_native_citizen_non_hispanic +
      total_native_citizen_hispanic
    ),
    total_naturalized_citizen = (
      total_naturalized_citizen_non_hispanic +
      total_naturalized_citizen_hispanic
    ),
    total_non_citizen = (
      total_non_citizen_non_hispanic +
      total_non_citizen_hispanic
    ),
    total_foreign_non_hispanic = (
      total_naturalized_citizen_non_hispanic +
      total_non_citizen_non_hispanic
    ),
    total_foreign_hispanic = (
      total_naturalized_citizen_hispanic +
      total_non_citizen_hispanic
    ),
    total_foreign = (
      total_foreign_non_hispanic +
      total_foreign_hispanic
    ),
    total_employees = (
        total_native_citizen +
        total_naturalized_citizen +
        total_non_citizen
    ),
    pct_native_citizen_non_hispanic = 
      pct(total_native_citizen_non_hispanic, total_employees),
    pct_native_citizen_hispanic =
      pct(total_native_citizen_hispanic, total_employees),
    pct_total_foreign_non_hispanic =
      pct(total_foreign_non_hispanic, total_employees),
    pct_total_foreign_hispanic =
      pct(total_foreign_hispanic, total_employees),
    pct_naturalized_citizen_non_hispanic =
      pct(total_naturalized_citizen_non_hispanic, total_employees),
    pct_naturalized_citizen_hispanic =
      pct(total_naturalized_citizen_hispanic, total_employees),
    pct_non_citizen_non_hispanic =
      pct(total_non_citizen_non_hispanic, total_employees),
    pct_non_citizen_hispanic =
      pct(total_non_citizen_hispanic, total_employees),
    pct_native_citizen =
      pct(total_native_citizen, total_employees),
    pct_total_foreign =
      pct(total_foreign, total_employees),
    pct_naturalized_citizen =
      pct(total_naturalized_citizen, total_employees),
    pct_non_citizen =
      pct(total_non_citizen, total_employees)
  )
}
ipums_food_production_selected_occupations_mapped

Calculate the national-level citizenship and ethnicity data for these industry-occupation pairs

ipums_food_production_by_industry_occupation <-
  ipums_food_production_selected_occupations_mapped %>%
  group_by(industry_code,
           industry,
           occupation_code,
           occupation,
           citizenship,
           ethnicity) %>%
  summarize(num_employees = sum(PERWT)) %>%
  pivot_wider(
    id_cols = c(industry_code, industry, occupation_code, occupation),
    names_from = c(citizenship, ethnicity),
    values_from = num_employees,
    names_prefix = "total_"
  ) %>%
  replace(is.na(.), 0) %>%
  calc_percents()
ipums_food_production_by_industry_occupation

Export the data

write_csv(
  ipums_food_production_by_industry_occupation,
  "data/exported/ipums_food_production_by_industry_occupation.csv"
)

Group the data by PUMA

ipums_food_production_by_puma <-
  ipums_food_production_selected_occupations_mapped %>%
  group_by(state_code,
           state,
           puma_code,
           puma,
           citizenship,
           ethnicity) %>%
  summarize(num_employees = sum(PERWT, na.rm = TRUE)) %>%
  pivot_wider(
    id_cols = c(state_code, state, puma_code, puma),
    names_from = c(citizenship, ethnicity),
    values_from = num_employees,
    names_prefix = "total_"
  ) %>%
  replace(is.na(.), 0) %>%
  calc_percents()
ipums_food_production_by_puma %>% select(puma_code,total_foreign)

Export the data

write_csv(
  ipums_food_production_by_puma,
  "data/exported/ipums_food_production_by_puma.csv"
)

Group the data by PUMA and industry and occupation

ipums_food_production_by_puma_ind_occ <-
  ipums_food_production_selected_occupations_mapped %>%
  group_by(
    state_code,
    state,
    puma_code,
    puma,
    industry_code,
    industry,
    occupation_code,
    occupation,
    citizenship,
    ethnicity
  ) %>%
  summarize(num_employees = sum(PERWT)) %>%
  pivot_wider(
    id_cols = c(
      state_code,
      state,
      puma_code,
      puma,
      industry_code,
      industry,
      occupation_code,
      occupation
    ),
    names_from = c(citizenship, ethnicity),
    values_from = num_employees,
    names_prefix = "total_"
  ) %>%
  replace(is.na(.), 0) %>%
  calc_percents()

Export the data

write_csv(
  ipums_food_production_by_puma_ind_occ,
  "data/exported/ipums_food_production_by_puma_ind_occ.csv"
)
ipums_food_production_by_puma

Join the employment data to the crosswalk data frame

ipums_food_production_by_puma
ipums_food_production_by_puma_crosswalked_to_county <-
  ipums_food_production_by_puma %>%
  left_join(crosswalk, by = "puma_code") %>%
  mutate(
    total_employees = round(
      total_employees * allocation_factor,
      digits = 0
    ),
    total_native_citizen_non_hispanic = round(total_native_citizen_non_hispanic *
                                          allocation_factor, digits = 0),
    total_native_citizen_hispanic = round(total_native_citizen_hispanic *
                                      allocation_factor, digits = 0),
    total_foreign_non_hispanic = round(total_foreign_non_hispanic *
                                         allocation_factor, digits = 0),
    total_foreign_hispanic = round(total_foreign_hispanic *
                                     allocation_factor, digits = 0),
    total_naturalized_citizen_non_hispanic = round(total_naturalized_citizen_non_hispanic
                                             * allocation_factor, digits = 0),
    total_naturalized_citizen_hispanic = round(total_naturalized_citizen_hispanic
                                         * allocation_factor, digits = 0),
    total_non_citizen_non_hispanic = round(total_non_citizen_non_hispanic
                                     * allocation_factor, digits = 0),
    total_non_citizen_hispanic = round(total_non_citizen_hispanic
                                 * allocation_factor, digits = 0),
    total_native_citizen = total_native_citizen_non_hispanic + total_native_citizen_hispanic,
    total_foreign = total_foreign_non_hispanic + total_foreign_hispanic,
    total_naturalized_citizen = total_naturalized_citizen_non_hispanic +
      total_naturalized_citizen_hispanic,
    total_non_citizen = total_non_citizen_non_hispanic + total_non_citizen_hispanic
  ) %>%
  select(1,
         state = state.x,
         3,
         puma = puma.x,
         32:33,
         35:40,
         5:17)
ipums_food_production_by_puma_crosswalked_to_county
ipums_food_production_by_puma_crosswalked_to_county %>% filter(county_code == "06053") %>% select(allocation_factor, total_employees, total_foreign, total_non_citizen)

Join the employment data to the crosswalk data frame

ipums_food_production_by_puma_ind_occ_crosswalked_to_county <-
  ipums_food_production_by_puma_ind_occ %>%
  left_join(crosswalk, by = "puma_code") %>%
  mutate(
    total_employees = round(
      total_employees * allocation_factor,
      digits = 0
    ),
    total_native_citizen_non_hispanic = round(total_native_citizen_non_hispanic
                                        * allocation_factor, digits = 0),
    total_native_citizen_hispanic = round(total_native_citizen_hispanic
                                    * allocation_factor, digits = 0),
    total_foreign_non_hispanic = round(total_foreign_non_hispanic
                                       * allocation_factor, digits = 0),
    total_foreign_hispanic = round(total_foreign_hispanic
                                   * allocation_factor, digits = 0),
    total_naturalized_citizen_non_hispanic = round(total_naturalized_citizen_non_hispanic
                                             * allocation_factor, digits = 0),
    total_naturalized_citizen_hispanic = round(total_naturalized_citizen_hispanic
                                         * allocation_factor, digits = 0),
    total_non_citizen_non_hispanic = round(total_non_citizen_non_hispanic
                                     * allocation_factor, digits = 0),
    total_non_citizen_hispanic = round(total_non_citizen_hispanic
                                 * allocation_factor, digits = 0),
    total_native_citizen = total_native_citizen_non_hispanic + total_native_citizen_hispanic,
    total_foreign = total_foreign_non_hispanic + total_foreign_hispanic,
    total_naturalized_citizen = total_naturalized_citizen_non_hispanic +
      total_naturalized_citizen_hispanic,
    total_non_citizen = total_non_citizen_non_hispanic + total_non_citizen_hispanic
  ) %>%
  select(1,
         state = state.x,
         3,
         puma = puma.x,
         36:37,
         5:8,
         39:44,
         9:21)
ipums_food_production_by_puma_crosswalked_to_county

Group the data by county

# This step is required to deal with situations
# where multiple PUMAs split a single county
ipums_food_production_by_county <-
  ipums_food_production_by_puma_crosswalked_to_county %>%
  group_by(state_code, state, county_code, county) %>%
  calc_percents()

Export the data

write_csv(
  ipums_food_production_by_county,
  "data/exported/ipums_food_production_by_county.csv"
)

Group the data by industry and occupation and county

ipums_food_production_by_puma_ind_occ_crosswalked_to_county
# This step is required to deal with situations
# where multiple PUMAs split a single county
ipums_food_production_by_county_ind_occ <-
  ipums_food_production_by_puma_ind_occ_crosswalked_to_county %>%
  group_by(
    state_code,
    state,
    county_code,
    county,
    industry_code,
    industry,
    occupation_code,
    occupation
  ) %>%
  calc_percents()
ipums_food_production_by_county_ind_occ

Export the data

write_csv(
  ipums_food_production_by_county_ind_occ,
  "data/exported/ipums_food_production_by_county_ind_occ.csv"
)

Analyze the data

What is the total number of workers employed in these industries?

sum(ipums_food_production_by_puma$total_employees)

What is the total number of foreigners employed in these industries?

sum(ipums_food_production_by_puma$total_foreign)

What’s that as a percent?

sum(ipums_food_production_by_puma$total_foreign) /
  sum(ipums_food_production_by_puma$total_employees) * 100

How many of the jobs have a higher proportion of foreigners employed than the national average of 17.1%?

ipums_food_production_by_industry_occupation %>%
  filter(pct_total_foreign > 17.1) %>%
  select(
    industry,
    occupation,
    total_employees,
    pct_total_foreign,
    pct_total_foreign_hispanic
  ) %>%
  arrange(desc(total_employees))

What is the total number of Hispanic foreigners employed in these industries?

sum(ipums_food_production_by_puma$total_foreign_hispanic)

What’s that as a percent of all foreign workers in these industries?

sum(ipums_food_production_by_puma$total_foreign_hispanic) /
  sum(ipums_food_production_by_puma$total_foreign) * 100

Which PUMAs have the highest number of immigrant foodworkers?

ipums_food_production_by_puma %>%
  arrange(desc(total_foreign)) %>%
  select(
    state,
    puma,
    total_employment_selected_industries,
    total_foreign,
    total_foreign_hispanic
  ) %>%
  head(23) # 2,341 PUMAs / 100 = 23.41

And how many immigrant workers are in these PUMAs?

ipums_food_production_by_puma %>%
  arrange(desc(total_foreign)) %>%
  select(puma,
         total_employment_selected_industries,
         total_foreign,
         total_foreign_hispanic) %>%
  head(23) %>%
  ungroup() %>%
  summarize(sum(total_foreign))

And how many of these foreign-born workers are Hispanic?

ipums_food_production_by_puma %>%
  arrange(desc(total_foreign)) %>%
  select(puma,
         total_employment_selected_industries,
         total_foreign,
         total_foreign_hispanic) %>%
  head(23) %>%
  ungroup() %>%
  summarize(sum(total_foreign_hispanic))

Which counties have the highest number of immigrant foodworkers?

ipums_food_production_by_county %>%
  arrange(desc(total_foreign)) %>%
  select(
    state,
    county,
    total_employment_selected_industries,
    total_foreign,
    total_foreign_hispanic
  ) %>%
  head(31) # 3,142 counties / 100 = 31.42

And how many immigrant workers are in these counties?

ipums_food_production_by_county %>%
  arrange(desc(total_foreign)) %>%
  select(
    county,
    total_employment_selected_industries,
    total_foreign,
    total_foreign_hispanic
  ) %>%
  head(31) %>%
  ungroup() %>%
  summarize(sum(total_foreign))

And how many of these foreign-born workers are Hispanic?

ipums_food_production_by_county %>%
  arrange(desc(total_foreign)) %>%
  select(
    county,
    total_employment_selected_industries,
    total_foreign,
    total_foreign_hispanic
  ) %>%
  head(31) %>%
  ungroup() %>%
  summarize(sum(total_foreign_hispanic))

What is the distribution of foreign workers in these industries by state?

foodworkers_by_state <- ipums_food_production_by_puma %>%
  group_by(state) %>%
  summarize(
    state_total_employment_selected_industries =
      sum(total_employees),
    state_total_foreign = sum(total_foreign),
    state_pct_total_foreign = round(
      sum(total_foreign) / sum(total_employees) * 100
    ),
    2,
    state_total_foreign_hispanic = sum(total_foreign_hispanic),
    state_pct_total_foreign_hispanic = round(
      sum(total_foreign_hispanic) /
        sum(total_employees) * 100
    ),
    2
  ) %>%
  mutate(
    rank_total_employment = dense_rank(desc(
      state_total_employment_selected_industries
    )),
    rank_total_foreign = dense_rank(desc(state_total_foreign)),
    rank_total_foreign_hispanic = dense_rank(desc(state_total_foreign_hispanic))
  ) %>%
  select(
    state,
    state_total_employment_selected_industries,
    state_total_foreign,
    state_pct_total_foreign,
    state_total_foreign_hispanic,
    state_pct_total_foreign_hispanic,
    rank_total_employment,
    rank_total_foreign,
    rank_total_foreign_hispanic
  ) %>%
  arrange(desc(state_total_employment_selected_industries))

foodworkers_by_state

What proportion of total foodworker employment do the top 10 states account for?

foodworkers_by_state %>%
  arrange(desc(state_total_employment_selected_industries)) %>%
  head(10) %>%
  summarize(sum(state_total_employment_selected_industries))

What is the distribution of foreign workers in these industries by state?

foodworkers_by_state %>%
  summarize(sum(state_total_employment_selected_industries))

Where do the “Red Zone” states stand?

red_zone <-
  data.frame(
    "state" = c(
      "Alabama/AL",
      "Arizona/AZ",
      "Arkansas/AR",
      "California/CA",
      "Florida/FL",
      "Georgia/GA",
      "Idaho/ID",
      "Iowa/IA",
      "Kansas/KS",
      "Louisiana/LA",
      "Mississippi/MS",
      "Missouri/MO",
      "Nevada/NV",
      "North Carolina/NC",
      "North Dakota/ND",
      "Oklahoma/OK",
      "South Carolina/SC",
      "Tennessee/TN",
      "Texas/TX",
      "Utah/UT",
      "Wisconsin/WI"
    ),
    "red_zone" = TRUE
  )

red_zone

Join with the red zone states data frame

foodworkers_by_state <- foodworkers_by_state %>%
  left_join(red_zone, by = "state")

Where do the Red Zone states stand?

foodworkers_by_state %>%
  filter(red_zone == TRUE)

Export the states

write_csv(foodworkers_by_state,
          "data/exported/foodworkers_by_state.csv")
LS0tCnRpdGxlOiAiY292aWQtaW1taWdyYW50LWZvb2R3b3JrZXJzIgphdXRob3I6ICJKb2UgWWVyYXJkaSIKZGF0ZTogIjUvNy8yMDIwIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGfQojIFdlIGRvbid0IHdhbnQgdG8gc2VlIGFueSB3YXJuaW5ncyBmcm9tIG91ciBjb2RlCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRikKCiMgV2UgZG9uJ3Qgd2FudCB0byBzZWUgYW55IG1lc3NhZ2VzCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRikKCiMgU2V0IGtleSBmaWxlIGZvciB0aGUgQ2Vuc3VzIEJ1cmVhdSBBUEkga2V5CmtleV9maWxlIDwtICJrZXlfZmlsZS50eHQiCmBgYAoKYGBge3IsIGluY2x1ZGUgPSBGfQpsaWJyYXJ5KGlwdW1zcikKbGlicmFyeShsYWJlbGxlZCkKbGlicmFyeShwdXJycikKbGlicmFyeShyZ2RhbCkKbGlicmFyeShzZikKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0aWdyaXMpCmBgYAoKIyBJbXBvcnQgYW5kIGZvcm1hdCBkYXRhCgojIyBJbXBvcnQgSVBVTVMKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIElQVU1TICgyMDE0LTE4IEFDUzsgcG9wdWxhdGlvbiA9IDE2IGFuZCBvbGRlcjsgZW1wbG95ZWQgLSBhdCB3b3JrLAojIGVtcGxveWVkIC0gbm90IGF0IHdvcmspCmlwdW1zIDwtIHJlYWQudGFibGUoImRhdGEvdXNhXzAwMDE1LmRhdCIpCmRkaSA8LSByZWFkX2lwdW1zX2RkaSgiZGF0YS91c2FfMDAwMTUueG1sIikKaXB1bXMgPC0gcmVhZF9pcHVtc19taWNybyhkZGkpICU+JQogIG11dGF0ZSgKICAgIHN0YXRlX2NvZGUgPSBhc19mYWN0b3IoVVMyMDE4Q19TVCwgbGV2ZWxzID0gInZhbHVlcyIpLAogICAgc3RhdGUgPSBhc19mYWN0b3IoVVMyMDE4Q19TVCwgbGV2ZWxzID0gImxhYmVscyIpLAogICAgcHVtYV9jb2RlID0gcGFzdGUwKHN0YXRlX2NvZGUsIGFzX2ZhY3RvcihVUzIwMThDX1BVTUEpKSwKICAgIGluZHVzdHJ5X2NvZGUgPSBhc19mYWN0b3IoVVMyMDE4Q19JTkRQLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBpbmR1c3RyeSA9IGFzX2ZhY3RvcihVUzIwMThDX0lORFAsIGxldmVscyA9ICJsYWJlbHMiKSwKICAgIG9jY3VwYXRpb25fY29kZSA9ICBhc19mYWN0b3IoVVMyMDE4Q19PQ0NQLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBvY2N1cGF0aW9uID0gYXNfZmFjdG9yKFVTMjAxOENfT0NDUCwgbGV2ZWxzID0gImxhYmVscyIpLAogICAgY2l0aXplbnNoaXBfY29kZSA9IGFzX2ZhY3RvcihDSVRJWkVOLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBjaXRpemVuc2hpcCA9IGFzX2ZhY3RvcihDSVRJWkVOLCBsZXZlbHMgPSAibGFiZWxzIiksCiAgICBldGhuaWNpdHlfY29kZSA9IGFzX2ZhY3RvcihISVNQQU4sIGxldmVscyA9ICJ2YWx1ZXMiKSwKICAgIGV0aG5pY2l0eSA9IGFzX2ZhY3RvcihISVNQQU4sIGxldmVscyA9ICJsYWJlbHMiKQogICkgJT4lCiAgc2VsZWN0KDE2OjI2LCA1KQoKaXB1bXMKYGBgCgojIyBQVU1BIHNoYXBlZmlsZXMKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwdW1hcyA8LSByZWFkT0dSKCJkYXRhL2lwdW1zX3B1bWFfMjAxMC9pcHVtc19wdW1hXzIwMTAuc2hwIikgJT4lCiAgIyBDb252ZXJ0IHNoYXBlZmlsZSB0byBzZiBvYmplY3QKICBzdF9hc19zZihjcnMgPSA1MDcwLCByZW1vdmUgPSBGKSAlPiUKICBzZWxlY3QocHVtYV9jb2RlID0gR0VPSUQsIHB1bWEgPSBOYW1lLCBnZW9tZXRyeSkKYGBgCgojIyBDb3VudHkgc2hhcGVmaWxlcwoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmNvdW50aWVzIDwtCiAgcmVhZE9HUigiZGF0YS90bF8yMDE5X3VzX2NvdW50eS90bF8yMDE5X3VzX2NvdW50eS5zaHAiKSAlPiUKICAjIENvbnZlcnQgc2hhcGVmaWxlIHRvIHNmIG9iamVjdAogIHN0X2FzX3NmKGNycyA9IDUwNzAsIHJlbW92ZSA9IEYpICU+JQogIHNlbGVjdChjb3VudHlfY29kZSA9IEdFT0lELCBjb3VudHkgPSBOQU1FTFNBRCwgZ2VvbWV0cnkpCmBgYAoKIyMgQ09WSUQgY291bnR5IGNhc2VzIGFuZCBkZWF0aHMKCmBgYHtyfQpjb3ZpZCA8LSByZWFkX2NzdigiZGF0YS91cy1jb3VudGllcy5jc3YiLAogICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gIj8iLCBkYXRlID0gIkQiKSkgJT4lCiAgcmVuYW1lKGNvdW50eV9jb2RlID0gZmlwcykgJT4lCiAgIyBGaWx0ZXIgdG8gdGhlIGxhdGVzdCBkYXRhIGZvciBlYWNoIGNvdW50eQogIGdyb3VwX2J5KGNvdW50eV9jb2RlKSAlPiUKICBzbGljZSh3aGljaC5tYXgoZGF0ZSkpCgpjb3ZpZApgYGAKCiMjIENvdW50eSBwb3B1bGF0aW9ucwoKIyMjIFJlYWQtaW4gQ2Vuc3VzIEFQSSBrZXkKCmBgYHtyfQpjZW5zdXNfa2V5IDwtIChyZWFkTGluZXMoa2V5X2ZpbGUpWzFdKQpgYGAKCiMjIyBDcmVhdGUgbGlzdCBvZiBhbGwgVVMgc3RhdGVzIHRvIGl0ZXJhdGUgdGhyb3VnaCBpbiB0aGUgQVBJIGNhbGxzCgpgYGB7cn0KdXMgPC0gdW5pcXVlKGZpcHNfY29kZXMkc3RhdGUpWzE6NTFdCgp1cwpgYGAKCiMjIyBEb3dubG9hZCBwb3B1bGF0aW9uIGRhdGEgZnJvbSB0aGUgMjAxNC0yMDE4IEFDUwoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnBvcHVsYXRpb24gPC0gbWFwX2Rmcih1cywgZnVuY3Rpb24oeCkgewogIGdldF9hY3MoCiAgICBnZW9ncmFwaHkgPSAiY291bnR5IiwKICAgIHZhcmlhYmxlcyA9ICJCMDEwMDFfMDAxIiwKICAgIHN0YXRlID0geCwKICAgIGtleSA9IGNlbnN1c19rZXkKICApCn0pICU+JQogIG11dGF0ZShpbmNvbWVfcXVhcnRpbGUgPSBudGlsZShlc3RpbWF0ZSwgNCkpICU+JQogIHNlbGVjdChjb3VudHlfY29kZSA9IEdFT0lELAogICAgICAgICBjb3VudHkgPSBOQU1FLAogICAgICAgICBwb3B1bGF0aW9uID0gZXN0aW1hdGUpCgpwb3B1bGF0aW9uCmBgYAoKIyMgUFVNQS10by1jb3VudHkgY3Jvc3N3YWxrCgpgYGB7cn0KY291bnR5X3RvX3B1bWFfY3Jvc3N3YWxrIDwtIHJlYWRfY3N2KCJkYXRhL2dlb2NvcnIyMDE4LmNzdiIsIHNraXAgPSAxKSAlPiUKICBtdXRhdGUocHVtYV9jb2RlID0gcGFzdGUwKGBTdGF0ZSBjb2RlYCwgYFBVTUEgKDIwMTIpYCkpICU+JQogIHNlbGVjdCgKICAgIHB1bWFfY29kZSwKICAgIGNvdW50eV9jb2RlID0gYENvdW50eSBjb2RlICgyMDE0KWAsCiAgICBzdGF0ZSA9IGBTdGF0ZSBhYmJyZXZpYXRpb25gLAogICAgY291bnR5ID0gYDIwMTQgY291bnR5IG5hbWVgLAogICAgcHVtYSA9IGBQVU1BMTIgbmFtZWAsCiAgICBhbGxvY2F0aW9uX2ZhY3RvciA9IGBwdW1hMTIgdG8gY291bnR5MTQgYWxsb2NhdGlvbiBmYWN0b3JgCiAgKQoKY291bnR5X3RvX3B1bWFfY3Jvc3N3YWxrCmBgYAoKIyMgSm9pbiB0aGUgQ09WSUQsIHBvcHVsYXRpb24gYW5kIGNyb3Nzd2FsayBkYXRhIGZyYW1lcwoKYGBge3J9CmNyb3Nzd2FsayA8LSBsaXN0KGNvdmlkLCBwb3B1bGF0aW9uLCBjb3VudHlfdG9fcHVtYV9jcm9zc3dhbGspICU+JQogIHJlZHVjZShmdWxsX2pvaW4sIGJ5ID0gImNvdW50eV9jb2RlIikgJT4lCiAgbXV0YXRlKAogICAgcHVtYSA9IHBhc3RlKHB1bWEsIHN0YXRlLngsIHNlcCA9ICIsICIpLAogICAgY2FzZXNfcGVyXzEwMGsgPSByb3VuZChjYXNlcyAvIHBvcHVsYXRpb24gKiAxMDAwMDAsIGRpZ2l0cyA9IDApLAogICAgZGVhdGhzX3Blcl8xMDBrID0gcm91bmQoZGVhdGhzIC8gcG9wdWxhdGlvbiAqIDEwMDAwMCwgZGlnaXRzID0gMCkKICApICU+JQogIHNlbGVjdCgKICAgIDEsCiAgICBzdGF0ZSA9IHN0YXRlLngsCiAgICBjb3VudHlfY29kZSwKICAgIGNvdW50eSA9IGNvdW50eS55LAogICAgcHVtYV9jb2RlLAogICAgcHVtYSwKICAgIHBvcHVsYXRpb24sCiAgICBjYXNlcywKICAgIGRlYXRocywKICAgIGNhc2VzX3Blcl8xMDBrLAogICAgZGVhdGhzX3Blcl8xMDBrLAogICAgYWxsb2NhdGlvbl9mYWN0b3IKICApCgpjcm9zc3dhbGsKYGBgCgojIyBGaWx0ZXIgdG8gdGhlIGZvb2QgcHJvZHVjdGlvbiBpbmR1c3RyaWVzIHdlJ3JlIGludGVyZXN0ZWQgaW4KCmBgYHtyfQpmb29kX3Byb2R1Y3Rpb25faW5kdXN0cmllcyA8LQogIGxpc3QoIjAxNzAiLCAjIENyb3AgcHJvZHVjdGlvbgogICAgICAgIjAxODAiLCAjIEFuaW1hbCBwcm9kdWN0aW9uIGFuZCBhcXVhY3VsdHVyZQogICAgICAgIjAyOTAiLCAjIFN1cHBvcnQgYWN0aXZpdGllcyBmb3IgYWdyaWN1bHR1cmUgYW5kIGZvcmVzdHJ5CiAgICAgICAiMTA3MCIsICMgQW5pbWFsIGZvb2QsIGdyYWluIGFuZCBvaWxzZWVkIG1pbGxpbmcKICAgICAgICIxMDgwIiwgIyBTdWdhciBhbmQgY29uZmVjdGlvbmVyeSBwcm9kdWN0cwogICAgICAgIjEwOTAiLCAjIEZydWl0IGFuZCB2ZWdldGFibGUgcHJlc2VydmluZyBhbmQgc3BlY2lhbHR5IGZvb2QgbWFudWZhY3R1cmluZwogICAgICAgIjExNzAiLCAjIERhaXJ5IHByb2R1Y3QgbWFudWZhY3R1cmluZwogICAgICAgIjExODAiLCAjIEFuaW1hbCBzbGF1Z2h0ZXJpbmcgYW5kIHByb2Nlc3NpbmcKICAgICAgICIxMjcwIiwgIyBCYWtlcmllcyBhbmQgdG9ydGlsbGEgbWFudWZhY3R1cmluZywgZXhjZXB0IHJldGFpbCBiYWtlcmllcwogICAgICAgIjEyODAiLCAjIFNlYWZvb2QgYW5kIG90aGVyIG1pc2NlbGxhbmVvdXMgZm9vZHM7IG4uZS5jLgogICAgICAgIjEyOTAiKSAjIE5vdCBzcGVjaWZpZWQgZm9vZCBpbmR1c3RyaWVzCgppcHVtc19mb29kX3Byb2R1Y3Rpb24gPC0gaXB1bXMgJT4lCiAgZmlsdGVyKGluZHVzdHJ5X2NvZGUgJWluJSBmb29kX3Byb2R1Y3Rpb25faW5kdXN0cmllcykKYGBgCgojIyBDYWxjdWxhdGUgZW1wbG95bWVudCBieSBpbmR1c3RyeS1vY2N1cGF0aW9uIGdyb3VwaW5nCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2VtcGxveW1lbnRfYnlfaW5kX29jYyA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbiAlPiUKICBncm91cF9ieShpbmR1c3RyeSwgb2NjdXBhdGlvbikgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QpKSAlPiUKICBwaXZvdF93aWRlcigKICAgIGlkX2NvbHMgPSBjKGluZHVzdHJ5LCBvY2N1cGF0aW9uKSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJudW1fZW1wbG95ZWVzIgogICkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lCiAgIyBFeGNsdWRlIGZyb20gb3VyIGFuYWx5c2lzIGluZC1vY2MgZ3JvdXBpbmdzCiAgIyB3aXRoIGZld2VyIHRoYW4gMiw1MDAgZW1wbG95ZWVzIG5hdGlvbmFsbHkKICBmaWx0ZXIobnVtX2VtcGxveWVlcyA+PSAyNTAwKQpgYGAKCiMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fZW1wbG95bWVudF9ieV9pbmRfb2NjLAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9lbXBsb3ltZW50X2J5X2luZF9vY2MuY3N2IgopCmBgYAoKIyMgRmlsdGVyIHRoZSBpbmR1c3RyeS1vY2N1cGF0aW9uIHBhaXJzCgojIyMgSW1wb3J0IGRhdGEgZnJhbWUgb2YgZm9vZCBwcm9kdWN0aW9uIGluZHVzdHJ5LW9jY3VwYXRpb24gcGFpcnMKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fZW1wbG95bWVudF9ieV9pbmRfb2NjIDwtCiAgcmVhZF9jc3YoImRhdGEvaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3RvdGFsX2VtcGxveW1lbnRfYnlfaW5kX29jYy5jc3YiKQpgYGAKCiMjIyBKb2luIHRoZSBpbmR1c3RyeS1vY2N1cGF0aW9uIHBhaXJzIHRvIHRoZSBpcHVtcyBkYXRhIGFuZCBmaWx0ZXIgdG8ganVzdCB0aGUgaW5kdXN0cnktb2NjdXBhdGlvbiBwYWlycyB3ZSB3YW50CgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uICU+JQogIGlubmVyX2pvaW4oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2VtcGxveW1lbnRfYnlfaW5kX29jYywKICAgICAgICAgICAgIGJ5ID0gYygiaW5kdXN0cnkiLCAib2NjdXBhdGlvbiIpKSAlPiUKICBmaWx0ZXIoZXhjbHVkZSA9PSBGQUxTRSkgJT4lCiAgc2VsZWN0KC1udW1fZW1wbG95ZWVzLCAtZXhjbHVkZSkKCmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9ucwpgYGAKCiMjIEFuZCBqb2luIHdpdGggdGhlIHB1bWFzIGRhdGEgZnJhbWUgdG8gZ2V0IHRoZSBQVU1BIG5hbWVzCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zICU+JQogIGxlZnRfam9pbihwdW1hcywgYnkgPSAicHVtYV9jb2RlIikgJT4lCiAgbXV0YXRlKHB1bWEgPSBwYXN0ZShwdW1hLCBzdGF0ZSwgc2VwID0gIiwgIikpICU+JQogIHNlbGVjdCgxOjMsCiAgICAgICAgIDEzLAogICAgICAgICA0OjEyKQoKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zCmBgYAoKYGBge3J9CmNpdGl6ZW5zaGlwX2xvb2t1cCA9IHRpYmJsZSgKICBjaXRpemVuc2hpcF9jb2RlID0gZmFjdG9yKGMoCiAgICAwLCAxLCAyLCAzLCA0LCA1CiAgKSksCiAgY2l0aXplbnNoaXAgPSBjKAogICAgIm5hdGl2ZV9jaXRpemVuIiwgIyBuL2EKICAgICJuYXRpdmVfY2l0aXplbiIsICMgYm9ybl9hYnJvYWRfY2l0aXplbgogICAgIm5hdHVyYWxpemVkX2NpdGl6ZW4iLCAjIG5hdHVyYWxpemVkX2NpdGl6ZW4KICAgICJub25fY2l0aXplbiIsICMgbm9uX2NpdGl6ZW4KICAgICJub25fY2l0aXplbl93aXRoX3BhcGVycyIsICMgbm9uX2NpdGl6ZW5fd2l0aF9wYXBlcnMKICAgICJmb3JlaWduX2Jvcm5fc3RhdHVzX3Vua25vd24iCiAgKQopCgpldGhuaWNpdHlfbG9va3VwID0gdGliYmxlKAogIGV0aG5pY2l0eV9jb2RlID0gZmFjdG9yKGMoCiAgICAwLCAxLCAyLCAzLCA0LCA5CiAgKSksCiAgZXRobmljaXR5ID0gYygKICAgICJub25faGlzcGFuaWMiLAogICAgImhpc3BhbmljIiwgIyBtZXhpY2FuCiAgICAiaGlzcGFuaWMiLCAjIHB1ZXJ0b19yaWNhbgogICAgImhpc3BhbmljIiwgIyBjdWJhbgogICAgImhpc3BhbmljIiwgIyBvdGhlcgogICAgIm5vdF9yZXBvcnRlZCIKICApCikKCmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQgPC0KICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fc2VsZWN0ZWRfb2NjdXBhdGlvbnMgJT4lCiAgc2VsZWN0KC1ldGhuaWNpdHksLWNpdGl6ZW5zaGlwKSAlPiUKICBsZWZ0X2pvaW4oZXRobmljaXR5X2xvb2t1cCwgYnk9ImV0aG5pY2l0eV9jb2RlIikgJT4lCiAgbGVmdF9qb2luKGNpdGl6ZW5zaGlwX2xvb2t1cCwgYnk9ImNpdGl6ZW5zaGlwX2NvZGUiKQpgYGAKCmBgYHtyfQpwY3QgPC0gZnVuY3Rpb24gKHBhcnQsd2hvbGUpIHsKICByb3VuZChwYXJ0IC8gd2hvbGUgKiAxMDAsIGRpZ2l0cyA9IDApCn0KYGBgCgoKYGBge3J9CmNhbGNfcGVyY2VudHMgPC0gZnVuY3Rpb24gKHJvd3MpIHsKICByb3dzICU+JQogIG11dGF0ZSgKICAgIHRvdGFsX25hdGl2ZV9jaXRpemVuID0gKAogICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW4gPSAoCiAgICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX25vbl9jaXRpemVuID0gKAogICAgICB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljID0gKAogICAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYyArCiAgICAgIHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMgPSAoCiAgICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgKwogICAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ24gPSAoCiAgICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2VtcGxveWVlcyA9ICgKICAgICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbiArCiAgICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbiArCiAgICAgICAgdG90YWxfbm9uX2NpdGl6ZW4KICAgICksCiAgICBwY3RfbmF0aXZlX2NpdGl6ZW5fbm9uX2hpc3BhbmljID0gCiAgICAgIHBjdCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfdG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9CiAgICAgIHBjdCh0b3RhbF9mb3JlaWduX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljID0KICAgICAgcGN0KHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYywgdG90YWxfZW1wbG95ZWVzKSwKICAgIHBjdF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbm9uX2NpdGl6ZW5fbm9uX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25vbl9jaXRpemVuX2hpc3BhbmljID0KICAgICAgcGN0KHRvdGFsX25vbl9jaXRpemVuX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdGl2ZV9jaXRpemVuID0KICAgICAgcGN0KHRvdGFsX25hdGl2ZV9jaXRpemVuLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X3RvdGFsX2ZvcmVpZ24gPQogICAgICBwY3QodG90YWxfZm9yZWlnbiwgdG90YWxfZW1wbG95ZWVzKSwKICAgIHBjdF9uYXR1cmFsaXplZF9jaXRpemVuID0KICAgICAgcGN0KHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW4sIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3Rfbm9uX2NpdGl6ZW4gPQogICAgICBwY3QodG90YWxfbm9uX2NpdGl6ZW4sIHRvdGFsX2VtcGxveWVlcykKICApCn0KYGBgCgoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQKYGBgCgojIyBDYWxjdWxhdGUgdGhlIG5hdGlvbmFsLWxldmVsIGNpdGl6ZW5zaGlwIGFuZCBldGhuaWNpdHkgZGF0YSBmb3IgdGhlc2UgaW5kdXN0cnktb2NjdXBhdGlvbiBwYWlycwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9pbmR1c3RyeV9vY2N1cGF0aW9uIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zX21hcHBlZCAlPiUKICBncm91cF9ieShpbmR1c3RyeV9jb2RlLAogICAgICAgICAgIGluZHVzdHJ5LAogICAgICAgICAgIG9jY3VwYXRpb25fY29kZSwKICAgICAgICAgICBvY2N1cGF0aW9uLAogICAgICAgICAgIGNpdGl6ZW5zaGlwLAogICAgICAgICAgIGV0aG5pY2l0eSkgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QpKSAlPiUKICBwaXZvdF93aWRlcigKICAgIGlkX2NvbHMgPSBjKGluZHVzdHJ5X2NvZGUsIGluZHVzdHJ5LCBvY2N1cGF0aW9uX2NvZGUsIG9jY3VwYXRpb24pLAogICAgbmFtZXNfZnJvbSA9IGMoY2l0aXplbnNoaXAsIGV0aG5pY2l0eSksCiAgICB2YWx1ZXNfZnJvbSA9IG51bV9lbXBsb3llZXMsCiAgICBuYW1lc19wcmVmaXggPSAidG90YWxfIgogICkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lCiAgY2FsY19wZXJjZW50cygpCmBgYAoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9pbmR1c3RyeV9vY2N1cGF0aW9uCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfaW5kdXN0cnlfb2NjdXBhdGlvbiwKICAiZGF0YS9leHBvcnRlZC9pcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfaW5kdXN0cnlfb2NjdXBhdGlvbi5jc3YiCikKYGBgCgojIyMgR3JvdXAgdGhlIGRhdGEgYnkgUFVNQQoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zX21hcHBlZCAlPiUKICBncm91cF9ieShzdGF0ZV9jb2RlLAogICAgICAgICAgIHN0YXRlLAogICAgICAgICAgIHB1bWFfY29kZSwKICAgICAgICAgICBwdW1hLAogICAgICAgICAgIGNpdGl6ZW5zaGlwLAogICAgICAgICAgIGV0aG5pY2l0eSkgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QsIG5hLnJtID0gVFJVRSkpICU+JQogIHBpdm90X3dpZGVyKAogICAgaWRfY29scyA9IGMoc3RhdGVfY29kZSwgc3RhdGUsIHB1bWFfY29kZSwgcHVtYSksCiAgICBuYW1lc19mcm9tID0gYyhjaXRpemVuc2hpcCwgZXRobmljaXR5KSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJ0b3RhbF8iCiAgKSAlPiUKICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUKICBjYWxjX3BlcmNlbnRzKCkKYGBgCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEgJT4lIHNlbGVjdChwdW1hX2NvZGUsdG90YWxfZm9yZWlnbikKYGBgCgojIyMgRXhwb3J0IHRoZSBkYXRhCgpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hLAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hLmNzdiIKKQpgYGAKCiMjIEdyb3VwIHRoZSBkYXRhIGJ5IFBVTUEgYW5kIGluZHVzdHJ5IGFuZCBvY2N1cGF0aW9uCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYyA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQgJT4lCiAgZ3JvdXBfYnkoCiAgICBzdGF0ZV9jb2RlLAogICAgc3RhdGUsCiAgICBwdW1hX2NvZGUsCiAgICBwdW1hLAogICAgaW5kdXN0cnlfY29kZSwKICAgIGluZHVzdHJ5LAogICAgb2NjdXBhdGlvbl9jb2RlLAogICAgb2NjdXBhdGlvbiwKICAgIGNpdGl6ZW5zaGlwLAogICAgZXRobmljaXR5CiAgKSAlPiUKICBzdW1tYXJpemUobnVtX2VtcGxveWVlcyA9IHN1bShQRVJXVCkpICU+JQogIHBpdm90X3dpZGVyKAogICAgaWRfY29scyA9IGMoCiAgICAgIHN0YXRlX2NvZGUsCiAgICAgIHN0YXRlLAogICAgICBwdW1hX2NvZGUsCiAgICAgIHB1bWEsCiAgICAgIGluZHVzdHJ5X2NvZGUsCiAgICAgIGluZHVzdHJ5LAogICAgICBvY2N1cGF0aW9uX2NvZGUsCiAgICAgIG9jY3VwYXRpb24KICAgICksCiAgICBuYW1lc19mcm9tID0gYyhjaXRpemVuc2hpcCwgZXRobmljaXR5KSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJ0b3RhbF8iCiAgKSAlPiUKICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUKICBjYWxjX3BlcmNlbnRzKCkKYGBgCgojIyMgRXhwb3J0IHRoZSBkYXRhCgpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2MsCiAgImRhdGEvZXhwb3J0ZWQvaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYy5jc3YiCikKYGBgCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEKYGBgCgojIyBKb2luIHRoZSBlbXBsb3ltZW50IGRhdGEgdG8gdGhlIGNyb3Nzd2FsayBkYXRhIGZyYW1lCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEKYGBgCgpgYGB7ciBjcm9zc3dhbGsgdGhlIGVtcGxveW1lbnQgZGF0YSBmcm9tIFBVTUFzIHRvIGNvdW50aWVzfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkgPC0KICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBsZWZ0X2pvaW4oY3Jvc3N3YWxrLCBieSA9ICJwdW1hX2NvZGUiKSAlPiUKICBtdXRhdGUoCiAgICB0b3RhbF9lbXBsb3llZXMgPSByb3VuZCgKICAgICAgdG90YWxfZW1wbG95ZWVzICogYWxsb2NhdGlvbl9mYWN0b3IsCiAgICAgIGRpZ2l0cyA9IDAKICAgICksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdGl2ZV9jaXRpemVuX2hpc3BhbmljICoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljICoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9oaXNwYW5pYyAqCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25vbl9jaXRpemVuX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0aXZlX2NpdGl6ZW4gPSB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKyB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYywKICAgIHRvdGFsX2ZvcmVpZ24gPSB0b3RhbF9mb3JlaWduX25vbl9oaXNwYW5pYyArIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMsCiAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuID0gdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX2hpc3BhbmljLAogICAgdG90YWxfbm9uX2NpdGl6ZW4gPSB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgKyB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICkgJT4lCiAgc2VsZWN0KDEsCiAgICAgICAgIHN0YXRlID0gc3RhdGUueCwKICAgICAgICAgMywKICAgICAgICAgcHVtYSA9IHB1bWEueCwKICAgICAgICAgMzI6MzMsCiAgICAgICAgIDM1OjQwLAogICAgICAgICA1OjE3KQpgYGAKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkKYGBgCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkgJT4lIGZpbHRlcihjb3VudHlfY29kZSA9PSAiMDYwNTMiKSAlPiUgc2VsZWN0KGFsbG9jYXRpb25fZmFjdG9yLCB0b3RhbF9lbXBsb3llZXMsIHRvdGFsX2ZvcmVpZ24sIHRvdGFsX25vbl9jaXRpemVuKQpgYGAKCiMjIyBKb2luIHRoZSBlbXBsb3ltZW50IGRhdGEgdG8gdGhlIGNyb3Nzd2FsayBkYXRhIGZyYW1lCmBgYHtyIGNyb3Nzd2FsayB0aGUgZW1wbG95bWVudCBkYXRhIGZyb20gUFVNQXMgYW5kIGluZC1vY2MgcGFpcnMgdG8gY291bnRpZXMgYW5kIGluZC1vY2MgcGFpcnN9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2NfY3Jvc3N3YWxrZWRfdG9fY291bnR5IDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYyAlPiUKICBsZWZ0X2pvaW4oY3Jvc3N3YWxrLCBieSA9ICJwdW1hX2NvZGUiKSAlPiUKICBtdXRhdGUoCiAgICB0b3RhbF9lbXBsb3llZXMgPSByb3VuZCgKICAgICAgdG90YWxfZW1wbG95ZWVzICogYWxsb2NhdGlvbl9mYWN0b3IsCiAgICAgIGRpZ2l0cyA9IDAKICAgICksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbm9uX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25hdGl2ZV9jaXRpemVuID0gdG90YWxfbmF0aXZlX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsgdG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMsCiAgICB0b3RhbF9mb3JlaWduID0gdG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMgKyB0b3RhbF9mb3JlaWduX2hpc3BhbmljLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbiA9IHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYywKICAgIHRvdGFsX25vbl9jaXRpemVuID0gdG90YWxfbm9uX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsgdG90YWxfbm9uX2NpdGl6ZW5faGlzcGFuaWMKICApICU+JQogIHNlbGVjdCgxLAogICAgICAgICBzdGF0ZSA9IHN0YXRlLngsCiAgICAgICAgIDMsCiAgICAgICAgIHB1bWEgPSBwdW1hLngsCiAgICAgICAgIDM2OjM3LAogICAgICAgICA1OjgsCiAgICAgICAgIDM5OjQ0LAogICAgICAgICA5OjIxKQpgYGAKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkKYGBgCgojIyBHcm91cCB0aGUgZGF0YSBieSBjb3VudHkKCmBgYHtyIGdyb3VwIHRoZSBkYXRhIGJ5IGNvdW50eX0KIyBUaGlzIHN0ZXAgaXMgcmVxdWlyZWQgdG8gZGVhbCB3aXRoIHNpdHVhdGlvbnMKIyB3aGVyZSBtdWx0aXBsZSBQVU1BcyBzcGxpdCBhIHNpbmdsZSBjb3VudHkKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eSA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2Nyb3Nzd2Fsa2VkX3RvX2NvdW50eSAlPiUKICBncm91cF9ieShzdGF0ZV9jb2RlLCBzdGF0ZSwgY291bnR5X2NvZGUsIGNvdW50eSkgJT4lCiAgY2FsY19wZXJjZW50cygpCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5LAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkuY3N2IgopCmBgYAoKIyMgR3JvdXAgdGhlIGRhdGEgYnkgaW5kdXN0cnkgYW5kIG9jY3VwYXRpb24gYW5kIGNvdW50eQoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2NfY3Jvc3N3YWxrZWRfdG9fY291bnR5CmBgYAoKYGBge3IgZ3JvdXAgdGhlIGRhdGEgYnkgaW5kdXN0cnkgYW5kIG9jY3VwYXRpb24gYW5kIGNvdW50eX0KIyBUaGlzIHN0ZXAgaXMgcmVxdWlyZWQgdG8gZGVhbCB3aXRoIHNpdHVhdGlvbnMKIyB3aGVyZSBtdWx0aXBsZSBQVU1BcyBzcGxpdCBhIHNpbmdsZSBjb3VudHkKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eV9pbmRfb2NjIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jY19jcm9zc3dhbGtlZF90b19jb3VudHkgJT4lCiAgZ3JvdXBfYnkoCiAgICBzdGF0ZV9jb2RlLAogICAgc3RhdGUsCiAgICBjb3VudHlfY29kZSwKICAgIGNvdW50eSwKICAgIGluZHVzdHJ5X2NvZGUsCiAgICBpbmR1c3RyeSwKICAgIG9jY3VwYXRpb25fY29kZSwKICAgIG9jY3VwYXRpb24KICApICU+JQogIGNhbGNfcGVyY2VudHMoKQpgYGAKCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eV9pbmRfb2NjCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHlfaW5kX29jYywKICAiZGF0YS9leHBvcnRlZC9pcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5X2luZF9vY2MuY3N2IgopCmBgYAoKIyBBbmFseXplIHRoZSBkYXRhCgojIyBXaGF0IGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygd29ya2VycyBlbXBsb3llZCBpbiB0aGVzZSBpbmR1c3RyaWVzPwoKYGBge3IgYW5hbHl6ZSBlbXBsb3ltZW50IGJ5IHRvdGFsIGZvcmVpZ259CnN1bShpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSR0b3RhbF9lbXBsb3llZXMpCmBgYAoKIyMgV2hhdCBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIGZvcmVpZ25lcnMgZW1wbG95ZWQgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyfQpzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZm9yZWlnbikKYGBgCgojIyBXaGF0J3MgdGhhdCBhcyBhIHBlcmNlbnQ/CgpgYGB7cn0Kc3VtKGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hJHRvdGFsX2ZvcmVpZ24pIC8KICBzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZW1wbG95ZWVzKSAqIDEwMApgYGAKCiMjIEhvdyBtYW55IG9mIHRoZSBqb2JzIGhhdmUgYSBoaWdoZXIgcHJvcG9ydGlvbiBvZiBmb3JlaWduZXJzIGVtcGxveWVkIHRoYW4gdGhlIG5hdGlvbmFsIGF2ZXJhZ2Ugb2YgMTcuMSU/CgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2luZHVzdHJ5X29jY3VwYXRpb24gJT4lCiAgZmlsdGVyKHBjdF90b3RhbF9mb3JlaWduID4gMTcuMSkgJT4lCiAgc2VsZWN0KAogICAgaW5kdXN0cnksCiAgICBvY2N1cGF0aW9uLAogICAgdG90YWxfZW1wbG95ZWVzLAogICAgcGN0X3RvdGFsX2ZvcmVpZ24sCiAgICBwY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2VtcGxveWVlcykpCmBgYAoKIyMgV2hhdCBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIEhpc3BhbmljIGZvcmVpZ25lcnMgZW1wbG95ZWQgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBmb3JlaWduIGFuZCBIaXNwYW5pY30Kc3VtKGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hJHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpCmBgYAoKIyMgV2hhdCdzIHRoYXQgYXMgYSBwZXJjZW50IG9mIGFsbCBmb3JlaWduIHdvcmtlcnMgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyfQpzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZm9yZWlnbl9oaXNwYW5pYykgLwogIHN1bShpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSR0b3RhbF9mb3JlaWduKSAqIDEwMApgYGAKCiMjIFdoaWNoIFBVTUFzIGhhdmUgdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIGltbWlncmFudCBmb29kd29ya2Vycz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBwdW1hfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZm9yZWlnbikpICU+JQogIHNlbGVjdCgKICAgIHN0YXRlLAogICAgcHVtYSwKICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgIHRvdGFsX2ZvcmVpZ24sCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBoZWFkKDIzKSAjIDIsMzQxIFBVTUFzIC8gMTAwID0gMjMuNDEKYGBgCgojIyBBbmQgaG93IG1hbnkgaW1taWdyYW50IHdvcmtlcnMgYXJlIGluIHRoZXNlIFBVTUFzPwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9mb3JlaWduKSkgJT4lCiAgc2VsZWN0KHB1bWEsCiAgICAgICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgICAgICAgdG90YWxfZm9yZWlnbiwKICAgICAgICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYykgJT4lCiAgaGVhZCgyMykgJT4lCiAgdW5ncm91cCgpICU+JQogIHN1bW1hcml6ZShzdW0odG90YWxfZm9yZWlnbikpCmBgYAoKIyMgQW5kIGhvdyBtYW55IG9mIHRoZXNlIGZvcmVpZ24tYm9ybiB3b3JrZXJzIGFyZSBIaXNwYW5pYz8KCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZm9yZWlnbikpICU+JQogIHNlbGVjdChwdW1hLAogICAgICAgICB0b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMsCiAgICAgICAgIHRvdGFsX2ZvcmVpZ24sCiAgICAgICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpICU+JQogIGhlYWQoMjMpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzdW1tYXJpemUoc3VtKHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpKQpgYGAKCiMjIFdoaWNoIGNvdW50aWVzIGhhdmUgdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIGltbWlncmFudCBmb29kd29ya2Vycz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBjb3VudHl9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2ZvcmVpZ24pKSAlPiUKICBzZWxlY3QoCiAgICBzdGF0ZSwKICAgIGNvdW50eSwKICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgIHRvdGFsX2ZvcmVpZ24sCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBoZWFkKDMxKSAjIDMsMTQyIGNvdW50aWVzIC8gMTAwID0gMzEuNDIKYGBgCgojIyBBbmQgaG93IG1hbnkgaW1taWdyYW50IHdvcmtlcnMgYXJlIGluIHRoZXNlIGNvdW50aWVzPwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2ZvcmVpZ24pKSAlPiUKICBzZWxlY3QoCiAgICBjb3VudHksCiAgICB0b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMsCiAgICB0b3RhbF9mb3JlaWduLAogICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICkgJT4lCiAgaGVhZCgzMSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHN1bW1hcml6ZShzdW0odG90YWxfZm9yZWlnbikpCmBgYAoKIyMgQW5kIGhvdyBtYW55IG9mIHRoZXNlIGZvcmVpZ24tYm9ybiB3b3JrZXJzIGFyZSBIaXNwYW5pYz8KCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5ICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9mb3JlaWduKSkgJT4lCiAgc2VsZWN0KAogICAgY291bnR5LAogICAgdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzLAogICAgdG90YWxfZm9yZWlnbiwKICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMKICApICU+JQogIGhlYWQoMzEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzdW1tYXJpemUoc3VtKHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpKQpgYGAKCiMjIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmb3JlaWduIHdvcmtlcnMgaW4gdGhlc2UgaW5kdXN0cmllcyBieSBzdGF0ZT8KCmBgYHtyIGFuYWx5c2lzIGVtcGxveW1lbnQgYW5kIENPVklEIHN0YXR1cyBieSBzdGF0ZX0KZm9vZHdvcmtlcnNfYnlfc3RhdGUgPC0gaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEgJT4lCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQogIHN1bW1hcml6ZSgKICAgIHN0YXRlX3RvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcyA9CiAgICAgIHN1bSh0b3RhbF9lbXBsb3llZXMpLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbiA9IHN1bSh0b3RhbF9mb3JlaWduKSwKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduID0gcm91bmQoCiAgICAgIHN1bSh0b3RhbF9mb3JlaWduKSAvIHN1bSh0b3RhbF9lbXBsb3llZXMpICogMTAwCiAgICApLAogICAgMiwKICAgIHN0YXRlX3RvdGFsX2ZvcmVpZ25faGlzcGFuaWMgPSBzdW0odG90YWxfZm9yZWlnbl9oaXNwYW5pYyksCiAgICBzdGF0ZV9wY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9IHJvdW5kKAogICAgICBzdW0odG90YWxfZm9yZWlnbl9oaXNwYW5pYykgLwogICAgICAgIHN1bSh0b3RhbF9lbXBsb3llZXMpICogMTAwCiAgICApLAogICAgMgogICkgJT4lCiAgbXV0YXRlKAogICAgcmFua190b3RhbF9lbXBsb3ltZW50ID0gZGVuc2VfcmFuayhkZXNjKAogICAgICBzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMKICAgICkpLAogICAgcmFua190b3RhbF9mb3JlaWduID0gZGVuc2VfcmFuayhkZXNjKHN0YXRlX3RvdGFsX2ZvcmVpZ24pKSwKICAgIHJhbmtfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9IGRlbnNlX3JhbmsoZGVzYyhzdGF0ZV90b3RhbF9mb3JlaWduX2hpc3BhbmljKSkKICApICU+JQogIHNlbGVjdCgKICAgIHN0YXRlLAogICAgc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbiwKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbl9oaXNwYW5pYywKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduX2hpc3BhbmljLAogICAgcmFua190b3RhbF9lbXBsb3ltZW50LAogICAgcmFua190b3RhbF9mb3JlaWduLAogICAgcmFua190b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBhcnJhbmdlKGRlc2Moc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzKSkKCmZvb2R3b3JrZXJzX2J5X3N0YXRlCmBgYAoKIyMgV2hhdCBwcm9wb3J0aW9uIG9mIHRvdGFsIGZvb2R3b3JrZXIgZW1wbG95bWVudCBkbyB0aGUgdG9wIDEwIHN0YXRlcyBhY2NvdW50IGZvcj8KCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBhcnJhbmdlKGRlc2Moc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzKSkgJT4lCiAgaGVhZCgxMCkgJT4lCiAgc3VtbWFyaXplKHN1bShzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMpKQpgYGAKCiMjIyBXaGF0IGlzIHRoZSBkaXN0cmlidXRpb24gb2YgZm9yZWlnbiB3b3JrZXJzIGluIHRoZXNlIGluZHVzdHJpZXMgYnkgc3RhdGU/CgpgYGB7cn0KZm9vZHdvcmtlcnNfYnlfc3RhdGUgJT4lCiAgc3VtbWFyaXplKHN1bShzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMpKQpgYGAKCiMjIyBXaGVyZSBkbyB0aGUgIlJlZCBab25lIiBzdGF0ZXMgc3RhbmQ/CgpgYGAge3J9CnJlZF96b25lIDwtCiAgZGF0YS5mcmFtZSgKICAgICJzdGF0ZSIgPSBjKAogICAgICAiQWxhYmFtYS9BTCIsCiAgICAgICJBcml6b25hL0FaIiwKICAgICAgIkFya2Fuc2FzL0FSIiwKICAgICAgIkNhbGlmb3JuaWEvQ0EiLAogICAgICAiRmxvcmlkYS9GTCIsCiAgICAgICJHZW9yZ2lhL0dBIiwKICAgICAgIklkYWhvL0lEIiwKICAgICAgIklvd2EvSUEiLAogICAgICAiS2Fuc2FzL0tTIiwKICAgICAgIkxvdWlzaWFuYS9MQSIsCiAgICAgICJNaXNzaXNzaXBwaS9NUyIsCiAgICAgICJNaXNzb3VyaS9NTyIsCiAgICAgICJOZXZhZGEvTlYiLAogICAgICAiTm9ydGggQ2Fyb2xpbmEvTkMiLAogICAgICAiTm9ydGggRGFrb3RhL05EIiwKICAgICAgIk9rbGFob21hL09LIiwKICAgICAgIlNvdXRoIENhcm9saW5hL1NDIiwKICAgICAgIlRlbm5lc3NlZS9UTiIsCiAgICAgICJUZXhhcy9UWCIsCiAgICAgICJVdGFoL1VUIiwKICAgICAgIldpc2NvbnNpbi9XSSIKICAgICksCiAgICAicmVkX3pvbmUiID0gVFJVRQogICkKCnJlZF96b25lCmBgYAoKIyMjIEpvaW4gd2l0aCB0aGUgcmVkIHpvbmUgc3RhdGVzIGRhdGEgZnJhbWUKCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSA8LSBmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBsZWZ0X2pvaW4ocmVkX3pvbmUsIGJ5ID0gInN0YXRlIikKYGBgCgojIyMgV2hlcmUgZG8gdGhlIFJlZCBab25lIHN0YXRlcyBzdGFuZD8KCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBmaWx0ZXIocmVkX3pvbmUgPT0gVFJVRSkKYGBgCgojIyBFeHBvcnQgdGhlIHN0YXRlcwoKYGBge3J9CndyaXRlX2Nzdihmb29kd29ya2Vyc19ieV9zdGF0ZSwKICAgICAgICAgICJkYXRhL2V4cG9ydGVkL2Zvb2R3b3JrZXJzX2J5X3N0YXRlLmNzdiIpCmBgYAo=